﻿namespace Bango.WindowsPhone7.SDK
{
	internal class BangoLogger
	{
		private System.Device.Location.GeoCoordinateWatcher _locationWatcher;

		private System.Threading.ManualResetEvent _postingReset = new System.Threading.ManualResetEvent(true);
		private System.Threading.ManualResetEvent _transmittingReset = new System.Threading.ManualResetEvent(false);
		private System.Boolean _postingResult;
		private System.String _applicationId;
		private BangoProfile _profileForPost;

		#region Properties

		private System.Boolean _logEvents = true;
		internal System.Boolean LogEvents
		{
			get { return _logEvents; }
			set { _logEvents = value; BangoStorage.SaveSetting<System.Boolean>("LogEvents", _logEvents); }

		}

		private System.Boolean _useOfflineStorage = true;
		internal System.Boolean UseOfflineStorage
		{
			get { return _useOfflineStorage; }
			set { _useOfflineStorage = value; BangoStorage.SaveSetting<System.Boolean>("UseOfflineStorage", _useOfflineStorage); }
		}


		private System.Int32 _sessionResumePeriod = BangoConstants.SETTING_SESSION_RESUME_PERIOD;
		internal System.Int32 SessionResumePeriod
		{
			get { return _sessionResumePeriod; }
			set { _sessionResumePeriod = value; BangoStorage.SaveSetting<System.Int32>("SessionResumePeriod", _sessionResumePeriod); }
		}

		private System.String _applicationVersion = System.String.Empty;
		internal System.String ApplicationVersion
		{
			get { return _applicationVersion; }
			set { _applicationVersion = value; BangoStorage.SaveSetting<System.String>("ApplicationVersion", _applicationVersion); }
		}


		private System.String _applicationType = System.String.Empty;
		internal System.String ApplicationType
		{
			get { return _applicationType; }
			set { _applicationType = value; BangoStorage.SaveSetting<System.String>("ApplicationType", _applicationType); }
		}

		private System.String _applicationChannel = System.String.Empty;
		internal System.String ApplicationChannel
		{
			get { return _applicationChannel; }
			set { _applicationChannel = value; BangoStorage.SaveSetting<System.String>("ApplicationChannel", _applicationChannel); }
		}

		private System.String _userId = System.String.Empty;
		internal System.String UserId
		{
			get { return _userId; }
			set { _userId = value; BangoStorage.SaveSetting<System.String>("UserId", _userId); }
		}

		private System.String _postURL = BangoConstants.SETTING_POST_URL;
		internal System.String PostURL
		{
			get { return _postURL; }
			set { _postURL = value; BangoStorage.SaveSetting<System.String>("PostURL", _postURL); }
		}

		//14-10-11 JP Add new LogEventsPerFile property to allow user to control storage characteristics
		internal System.Int32 LogEventsPerFile
		{
			get { return BangoStorage.EventsPerFile; }
			set { BangoStorage.EventsPerFile = value; BangoStorage.SaveSetting<System.Int32>("EventsPerFile", BangoStorage.EventsPerFile); }
		}

		private System.Boolean _findLocation = true;
		internal System.Boolean FindLocation
		{
			get { return _findLocation; }
			set { _findLocation = value; BangoStorage.SaveSetting<System.Boolean>("FindLocation", _findLocation); }
		}

		private System.String _locationSource = BangoConstants.LOCATION_GPS;
		internal System.String LocationSource
		{
			get { return _locationSource; }
			set { _locationSource = value; BangoStorage.SaveSetting<System.String>("LocationSource", _locationSource); }
		}

		private System.String _userAgent = System.String.Empty;
		internal System.String UserAgent
		{
			get { return _userAgent; }
			set { _userAgent = value; BangoStorage.SaveSetting<System.String>("UserAgent", _userAgent); }
		}

		#endregion 

		/// <summary>
		/// Initialises the storage, and loads any existing settings
		/// </summary>
		internal BangoLogger()
		{

			BangoStorage.InitStorage(UseOfflineStorage);
			LoadSettings();
		}

		/// <summary>
		/// Loads any existing settings - required for tombstoning
		/// </summary>
		private void LoadSettings()
		{
			LogEvents = BangoStorage.LoadSetting<System.Boolean>("LogEvents", LogEvents);
			FindLocation = BangoStorage.LoadSetting<System.Boolean>("FindLocation", FindLocation);
			UseOfflineStorage = BangoStorage.LoadSetting<System.Boolean>("UseOfflineStorage", UseOfflineStorage);

			SessionResumePeriod = BangoStorage.LoadSetting<System.Int32>("SessionResumePeriod", SessionResumePeriod);

			ApplicationVersion = BangoStorage.LoadSetting<System.String>("ApplicationVersion", ApplicationVersion);
			ApplicationType = BangoStorage.LoadSetting<System.String>("ApplicationType", ApplicationType);
			ApplicationChannel = BangoStorage.LoadSetting<System.String>("ApplicationChannel", ApplicationChannel);
			UserId = BangoStorage.LoadSetting<System.String>("UserId", UserId);
			PostURL = BangoStorage.LoadSetting<System.String>("PostURL", PostURL);
			LocationSource = BangoStorage.LoadSetting<System.String>("LocationSource", LocationSource);

			BangoStorage.ProfileId = BangoStorage.LoadSetting<System.Int32>("ProfileId", BangoStorage.ProfileId);
			//12-10-11 JP fetch EventFileName, which is the latest file that the events are stored in
			BangoStorage.EventFileName = BangoStorage.LoadSetting<System.String>("BangoEventFileName", BangoStorage.EventFileName);
			BangoStorage.EventsPerFile = BangoStorage.LoadSetting<System.Int32>("EventsPerFile", BangoStorage.EventsPerFile);
		}
		
		/// <summary>
		/// Initialises the logging system.
		/// </summary>
		/// <param name="applicationId">The application Id of the application. This should be setup in the Bango Management Tools prior to use.</param>
		internal void InitLogger(System.String applicationId)
		{
			System.Double locationLatitude = 0;
			System.Double locationLongitude = 0;
			System.Double locationAltitude = 0;
			System.Double locationAccuracy = 0;

			_applicationId = applicationId;

			SetApplicationVersion();
			SetUserId();

			BangoStorage.LogProfile(UseOfflineStorage, BangoConstants.SDK_TYPE, BangoConstants.SDK_VERSION, _applicationId, ApplicationType, ApplicationChannel, ApplicationVersion, UserId, SessionResumePeriod, ConnectionType(), IsRoaming(), LocationSource, locationAltitude, locationLatitude, locationLongitude, locationAccuracy, BangoConstants.HARD_CODED_NETWORK_OPERATOR, BangoConstants.HARD_CODED_NETWORK_OPERATOR_NAME, BangoConstants.HARD_CODED_SIM_COUNTRY_ISO, BangoConstants.HARD_CODED_SIM_OPERATOR, BangoConstants.HARD_CODED_DEVICE_BUILD_BRAND, BangoConstants.DEVICE_BUILD_DEVICE, BangoConstants.DEVICE_BUILD_MODEL, BangoConstants.HARD_CODED_DEVICE_BUILD_PRODUCT, BangoConstants.DEVICE_BUILD_VERSION, BangoConstants.DEVICE_BUILD_ID, BangoConstants.HARD_CODED_NETWORK_TYPE);

			//This goes after the logging of the profile as you dont have it at time of logging
			GetLocation();

		}

		/// <summary>
		/// Posts any stored events, with an option to post the current profile.
		/// </summary>
		/// <param name="delayedStartObject">An System.Int32 Value that delays the start of the new thread by that number of seconds.</param>
		internal void PostEvents(System.Object bangoPosterObject)
		{

			_postingReset.WaitOne();

			BangoPoster bangoPoster = new BangoPoster(0, true);

			if (bangoPosterObject is BangoPoster)
			{
				bangoPoster = (BangoPoster)bangoPosterObject;
				if (bangoPoster.DelayedStart > 0)
				{
					System.Threading.Thread.Sleep(SessionResumePeriod * 1000);
				}
			}

			try
			{
				_postingReset.Reset();

				_profileForPost = null;

				if (BangoStorage.BangoStore != null)
				{
					//13-10-11 JP remember list of event store files to delete
					System.String[] eventFilesToDelete = BangoStorage.GetFileNamesToDelete();
					//force subsequent events into a new file
					BangoStorage.EventFileName = BangoStorage.GetNewEventFileName();
					BangoStorage.BangoEventStore = new System.Collections.Generic.List<BangoEvent>();
					System.Int32[] tempProfileMaxEventIds = new System.Int32[BangoStorage.BangoStore.Count];
					System.Boolean[] tempPostedProfileSuccessful = new System.Boolean[BangoStorage.BangoStore.Count];

					for (System.Int32 profileCounter = 0; profileCounter < BangoStorage.BangoStore.Count; profileCounter++)
					{
						if (bangoPoster.PostCurrentProfile || BangoStorage.BangoStore[profileCounter].ProfileId != BangoStorage.ProfileId)
						{
							_profileForPost = BangoStorage.BangoStore[profileCounter].GetProfileForPost();
							//13-10-11 JP keep a track of the current profile max event ids
							if (_profileForPost.Events.Count > 0)
							{
								tempProfileMaxEventIds[profileCounter] = _profileForPost.Events[_profileForPost.Events.Count - 1].EventId;
							}
							else
							{
								tempProfileMaxEventIds[profileCounter] = 0;
							}
							if (_profileForPost.Events.Count > 0)
							{
								if (PostEventsForProfile())
								{
									tempPostedProfileSuccessful[profileCounter] = true;
								}
								else
								{
									tempPostedProfileSuccessful[profileCounter] = false;
								}
							}
							//14-10-11 JP Don't remove old profiles here - it gets the arrays out of synch
							//else
							//{
							//    if (BangoStorage.BangoStore[profileCounter].ProfileId != BangoStorage.ProfileId)
							//    {
							//        BangoStorage.DeleteProfilePosted(UseOfflineStorage, BangoStorage.BangoStore[profileCounter]);
							//        profileCounter--;
							//    }
							//}
						}
					}
					//13-10-11 JP loop round, tidying up latest event file and removing the posted events from the profile
					System.Boolean saveFile = false;
					for (System.Int32 profileCounter = 0; profileCounter < BangoStorage.BangoStore.Count; profileCounter++)
					{
						if (bangoPoster.PostCurrentProfile || BangoStorage.BangoStore[profileCounter].ProfileId != BangoStorage.ProfileId)
						{
							//Tidy up the current event file - removing sent entries that have come in concurrently, if any						
							foreach (BangoEvent myEvent in BangoStorage.BangoEventStore)
							{
								if (myEvent.ProfileId == BangoStorage.BangoStore[profileCounter].ProfileId && myEvent.EventId <= tempProfileMaxEventIds[profileCounter])
								{
									BangoStorage.BangoEventStore.Remove(myEvent);
									saveFile = true;
								}
							}
							//Remove the sent events from the profile in memory
							BangoStorage.DeleteEventsPosted(_useOfflineStorage, BangoStorage.BangoStore[profileCounter].ProfileId, tempProfileMaxEventIds[profileCounter]);
						}
					}
					if (saveFile)
					{
						BangoStorage.SaveEventStore(_useOfflineStorage);
					}
					//14-10-11 JP Now remove the profiles that have no events
					for (System.Int32 profileCounter = 0; profileCounter < BangoStorage.BangoStore.Count; profileCounter++)
					{
						if (BangoStorage.BangoStore[profileCounter].Events.Count == 0 && BangoStorage.BangoStore[profileCounter].ProfileId != BangoStorage.ProfileId)
						{
							BangoStorage.DeleteProfilePosted(UseOfflineStorage, BangoStorage.BangoStore[profileCounter]);
							profileCounter--;
						}
					}
					//13-10-11 JP Call to delete old event files
					BangoStorage.DeleteOldEventFiles(_useOfflineStorage, eventFilesToDelete);
				}
			}
			catch (System.Exception ex)
			{
				System.Diagnostics.Debug.WriteLine(ex.Message);
			}
			finally
			{
				_postingReset.Set();
			}
		}

		/// <summary>
		/// Sets the application version if it's not been specified.
		/// </summary>
		private void SetApplicationVersion()
		{
			System.String[] version;
			try
			{
				if (System.String.IsNullOrEmpty(ApplicationVersion))
				{
					version = System.Reflection.Assembly.GetCallingAssembly().FullName.Split(',');
					if (version.Length > 1 && version[1].IndexOf('=') > -1)
					{

						ApplicationVersion = version[1].Substring(version[1].IndexOf('=') + 1);
					}
				}
				if (System.String.IsNullOrEmpty(ApplicationVersion))
				{
					ApplicationVersion = BangoConstants.UNKNOWN_VERSION;
				}

			}
			catch (System.Exception ex)
			{
				ApplicationVersion = BangoConstants.ERROR_VERSION;
				LogInternalErrorWarning(ex);
			}

		}

		/// <summary>
		/// Sets the user id if it's not been specified.
		/// </summary>
		private void SetUserId()
		{

			try
			{
				if (System.String.IsNullOrEmpty(UserId))
				{
					UserId = System.Convert.ToBase64String((System.Byte[])Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceUniqueId"));
				}
				if (System.String.IsNullOrEmpty(UserId))
				{
					UserId = BangoConstants.UNKNOWN_USERID;
				}

			}
			catch (System.Exception ex)
			{
				UserId = BangoConstants.UNKNOWN_USERID;
				LogInternalErrorWarning(ex);
			}
		}

		/// <summary>
		/// Returns whether or not a network connection is available.
		/// </summary>
		/// <returns>Returns whether or not a network connection is available.</returns>
		private System.Boolean IsConnected()
		{
			return Microsoft.Phone.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
		}

		/// <summary>
		/// Gets the connection type.
		/// If the connection is a WiFi connection this will be returned.
		/// Otherwise the operator connection type will be returned.
		/// </summary>
		/// <returns>The connection type in integer value. This is converted to a textual value on posting.</returns>
		private System.Int32 ConnectionType()
		{
			switch (Microsoft.Phone.Net.NetworkInformation.NetworkInterface.NetworkInterfaceType)
			{
				case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Wireless80211:
				//COMMENT: Setting ethernet to wireless as when you are connected by usb that's what the connection is
				case Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType.Ethernet:
					return BangoConstants.WIFI_CONNECTION;
				default:
					return (System.Int32)Microsoft.Phone.Net.NetworkInformation.NetworkInterface.NetworkInterfaceType;
			}
		}

		/// <summary>
		/// Gets whether or not the user is currently roaming. 
		/// Currently this is not available in the Windows Phone 7 SDK.
		/// So is always set to false
		/// </summary>
		/// <returns>Whether or not the user is currently roaming. Currently this is not available in the Windows Phone 7 SDK.</returns>
		private System.Boolean IsRoaming()
		{
			return BangoConstants.HARD_CODED_IS_ROAMING;
		}

		/// <summary>
		/// Gets whether or not the user is currently using a WiFi connection.
		/// </summary>
		/// <returns>Whether or not the user is currently using a WiFi connection.</returns>
		private System.Boolean IsWifiConnection()
		{
			return ConnectionType() == BangoConstants.WIFI_CONNECTION;
		}

		/// <summary>
		/// Logs an event to the internal logging engine.
		/// </summary>
		/// <param name="eventName">The name of the event to log.</param>
		/// <param name="errorLevel">The error level of the event to log.</param>
		/// <param name="eventValue">The value of the event to log.</param>
		/// <param name="eventDetail">The detail of the event to log.</param>
		/// <param name="errorId">The error Id of the event to log.</param>
		/// <param name="eventParameters">Any custom parameters to log with events.</param>
		/// <returns>The internal id of the event.</returns>
		private System.Int32 LogEvent(System.String eventName, System.Int32 errorLevel, System.String eventValue, System.String eventDetail, System.String errorId, System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<System.String, System.String>> eventParameters)
		{
			System.Int32 returnValue = -1;
			System.DateTime eventTime = System.DateTime.UtcNow;
			System.DateTime eventLocalTime = System.DateTime.Now;
			System.Collections.Generic.List<BangoEventParameter> eventParametersPairs = null;

			if (LogEvents)
			{
				if (eventParameters != null)
				{
					eventParametersPairs = new System.Collections.Generic.List<BangoEventParameter>();
					foreach (System.Collections.Generic.KeyValuePair<System.String, System.String> eventParameter in eventParameters)
					{
						eventParametersPairs.Add(new BangoEventParameter(eventParameter.Key, eventParameter.Value));
					}
				}

				returnValue = BangoStorage.LogEvent(UseOfflineStorage, ConnectionType(), BangoConstants.HARD_CODED_OPERATOR_CONNECTION_TYPE, errorLevel, eventName, eventDetail, eventValue, errorId, eventTime, eventLocalTime, eventParametersPairs);
			}
			return returnValue;
		}

		/// <summary>
		/// Logs an event to the internal logging engine.
		/// </summary>
		/// <param name="eventName">The name of the event to log.</param>
		/// <param name="eventValue">The value of the event to log.</param>
		/// <param name="eventDetail">The detail of the event to log.</param>
		/// <param name="eventParameters">Any custom parameters to log with events.</param>
		/// <returns>The internal id of the event.</returns>
		internal System.Int32 LogEvent(System.String eventName, System.String eventValue, System.String eventDetail, System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<System.String, System.String>> eventParameters)
		{
			return LogEvent(eventName, BangoConstants.ERROR_NONE, eventValue, eventDetail, "", eventParameters);
		}

		/// <summary>
		/// Logs an the session start event to the internal logging engine.
		/// </summary>
		/// <param name="eventValue">The value of the event to log.</param>
		/// <param name="eventDetail">The detail of the event to log.</param>
		/// <param name="eventParameters">Any custom parameters to log with events.</param>
		/// <returns>The internal id of the event.</returns>
		internal System.Int32 LogEventStart(System.String eventValue, System.String eventDetail, System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<System.String, System.String>> eventParameters)
		{
			return LogEvent(BangoSessionEvents.SESSION_START, eventValue, eventDetail, eventParameters);
		}

		/// <summary>
		/// Logs an the session end event to the internal logging engine.
		/// </summary>
		/// <param name="eventValue">The value of the event to log.</param>
		/// <param name="eventDetail">The detail of the event to log.</param>
		/// <param name="eventParameters">Any custom parameters to log with events.</param>
		/// <returns>The internal id of the event.</returns>
		internal System.Int32 LogEventEnd(System.String eventValue, System.String eventDetail, System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<System.String, System.String>> eventParameters)
		{
			return LogEvent(BangoSessionEvents.SESSION_END, eventValue, eventDetail, eventParameters);
		}

		/// <summary>
		/// Logs an error event to the internal logging engine.
		/// </summary>
		/// <param name="errorId">The error Id of the event to log.</param>
		/// <param name="message">The error message.</param>
		/// <param name="errorClass">The class in which the error occurred.</param>
		/// <param name="eventParameters">Any custom parameters to log with events.</param>
		/// <returns>The internal id of the error.</returns>
		internal System.Int32 LogEventError(System.String errorId, System.String message, System.String errorClass, System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<System.String, System.String>> eventParameters)
		{
			return LogEvent(BangoSessionEvents.EVENT_ERROR, BangoConstants.ERROR_USER, errorClass, message, errorId, eventParameters);
		}
		
		/// <summary>
		/// Logs a critical internal error event to the internal logging engine.
		/// </summary>
		/// <param name="ex">The error that was raised.</param>
		/// <returns>The internal id of the error.</returns>
		internal System.Int32 LogInternalErrorCritical(System.Exception ex)
		{
			return LogInternalError(ex, BangoConstants.ERROR_INTERNAL_CRITICAL);
		}

		/// <summary>
		/// Logs a internal warning error event to the internal logging engine.
		/// </summary>
		/// <param name="ex">The error that was raised.</param>
		/// <returns>The internal id of the error.</returns>
		internal System.Int32 LogInternalErrorWarning(System.Exception ex)
		{
			return LogInternalError(ex, BangoConstants.ERROR_INTERNAL_WARNING);
		}

		/// Logs an internal error event to the internal logging engine.
		/// </summary>
		/// <param name="ex">The error that was raised.</param>
		/// <param name="errorLevel">The error level of the error (Warning/Critical).</param>
		/// <returns>The internal id of the error.</returns>
		private System.Int32 LogInternalError(System.Exception ex, System.Int32 errorLevel)
		{
			return LogEvent("", errorLevel, ex.StackTrace, ex.Message, "", null);
		}

		/// <summary>
		/// Initialises the location finder if required.
		/// </summary>
		private void GetLocation()
		{
			if (FindLocation)
			{
				if (LocationSource == BangoConstants.LOCATION_CELL)
				{
					_locationWatcher = new System.Device.Location.GeoCoordinateWatcher(System.Device.Location.GeoPositionAccuracy.High);
				}
				else
				{
					_locationWatcher = new System.Device.Location.GeoCoordinateWatcher(System.Device.Location.GeoPositionAccuracy.Default);
				}
				_locationWatcher.MovementThreshold = 20;

				// Add event handlers for StatusChanged and PositionChanged events
				_locationWatcher.StatusChanged += new System.EventHandler<System.Device.Location.GeoPositionStatusChangedEventArgs>(_locationWatcher_StatusChanged);
				_locationWatcher.PositionChanged += new System.EventHandler<System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate>>(_locationWatcher_PositionChanged);

				// Start data acquisition
				_locationWatcher.Start();
			}
		}

		/// <summary>
		/// Destroys the location finder.
		/// </summary>
		internal void EndLocationUpdates()
		{
			if (FindLocation && _locationWatcher != null)
			{
				_locationWatcher.Stop();
				//_locationWatcher.StatusChanged -= new System.EventHandler<System.Device.Location.GeoPositionStatusChangedEventArgs>(_locationWatcher_StatusChanged);
				//_locationWatcher.PositionChanged -= new System.EventHandler<System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate>>(_locationWatcher_PositionChanged);
				_locationWatcher = null;
			}
		}

		/// <summary>
		/// Handler for the location StatusChanged event.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _locationWatcher_StatusChanged(object sender, System.Device.Location.GeoPositionStatusChangedEventArgs e)
		{
			switch (e.Status)
			{
				case System.Device.Location.GeoPositionStatus.Disabled:
					// The location service is disabled or unsupported.
					// Alert the user
					EndLocationUpdates();
					break;
			}

		}

		/// <summary>
		/// Handler for the location PositionChanged event.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _locationWatcher_PositionChanged(object sender, System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate> e)
		{

			if (!e.Position.Location.IsUnknown)
			{
				BangoStorage.UpdateProfileLocation(UseOfflineStorage, e.Position.Location.Latitude, e.Position.Location.Longitude, e.Position.Location.Altitude, e.Position.Location.HorizontalAccuracy);
				EndLocationUpdates();
			}
		}

		/// <summary>
		/// Posts the supplied profile and associated events to the specified url.
		/// </summary>
		/// <returns>Whether or not the profile and associated events were posted successfully.</returns>
		private System.Boolean PostEventsForProfile()
		{
			System.Net.HttpWebRequest request;

			try
			{
				_transmittingReset.Reset();
				_postingResult = false;
				if (LogEvents && IsConnected() && (!IsRoaming() || IsWifiConnection()))
				{
					request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(PostURL);
					request.Method = "POST";
					request.ContentType = "application/json";

					if (UserAgent != null && UserAgent != "")
					{
						request.Headers["User-Agent"] = UserAgent;
					}
					request.BeginGetRequestStream(new System.AsyncCallback(GetRequestStreamCallback), request);
					_transmittingReset.WaitOne();
				}
			}
			catch (System.Exception)
			{
				_postingResult = false;
			}


			return _postingResult;

		}

		private void GetRequestStreamCallback(System.IAsyncResult asynchronousResult)
		{
			System.Net.HttpWebRequest request;
			System.Runtime.Serialization.Json.DataContractJsonSerializer jsonSerializer;
			System.String postData = System.String.Empty;
			System.Byte[] postBytes;
			try
			{
				request = (System.Net.HttpWebRequest)asynchronousResult.AsyncState;
				using (System.IO.Stream postStream = request.EndGetRequestStream(asynchronousResult))
				{
					jsonSerializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(BangoProfile));
					using (System.IO.MemoryStream jsonMemory = new System.IO.MemoryStream())
					{
						_profileForPost.ConnectionType = BangoStatic.ConnectionType(ConnectionType());
						_profileForPost.OperatorConnectionType = BangoStatic.OperatorConnectionType(BangoConstants.HARD_CODED_OPERATOR_CONNECTION_TYPE);
						jsonSerializer.WriteObject(jsonMemory, _profileForPost);

						using (System.IO.StreamReader jsonStream = new System.IO.StreamReader(jsonMemory))
						{
							jsonMemory.Position = 0;
							postData = jsonStream.ReadToEnd();
						}
					}

					postBytes = System.Text.Encoding.UTF8.GetBytes(postData);
					postStream.Write(postBytes, 0, postBytes.Length);
					postStream.Close();
				}
				// Start the asynchronous operation to get the response
				request.BeginGetResponse(new System.AsyncCallback(GetResponseCallback), request);
			}
			catch (System.Exception )
			{
				_transmittingReset.Set();
			}
		}

		private void GetResponseCallback(System.IAsyncResult asynchronousResult)
		{
			System.Net.HttpWebRequest request;
			System.Net.HttpWebResponse response;
			try
			{
				request = (System.Net.HttpWebRequest)asynchronousResult.AsyncState;
				using (response = (System.Net.HttpWebResponse)request.EndGetResponse(asynchronousResult))
				{

					_postingResult = response.StatusCode == System.Net.HttpStatusCode.OK;
					response.Close();
				}
			}
			catch (System.Exception)
			{
			}
			finally
			{
				_transmittingReset.Set();
			}

		}

		public string viewBatch()
		{
			BangoProfile bProfile = BangoStorage.GetProfile(BangoStorage.ProfileId).GetProfileForPost();

			System.Runtime.Serialization.Json.DataContractJsonSerializer jsonSerializer;
			System.String jsonData = System.String.Empty;
			
			jsonSerializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(BangoProfile));
			using (System.IO.MemoryStream jsonMemory = new System.IO.MemoryStream())
			{
				bProfile.ConnectionType = BangoStatic.ConnectionType(ConnectionType());
				bProfile.OperatorConnectionType = BangoStatic.OperatorConnectionType(BangoConstants.HARD_CODED_OPERATOR_CONNECTION_TYPE);
				jsonSerializer.WriteObject(jsonMemory, bProfile);

				using (System.IO.StreamReader jsonStream = new System.IO.StreamReader(jsonMemory))
				{
					jsonMemory.Position = 0;
					jsonData = jsonStream.ReadToEnd();
				}
			}

			return jsonData;							
		}
	}
}
